package Server.ExtComponents.MyBatis;

import Server.ExtComponents.BaseConfig.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.jolbox.bonecp.BoneCPConfig;
import com.jolbox.bonecp.BoneCPDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.*;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

@Service
public class OrmProviderFactory {

    private static final Logger LOGGER = LoggerFactory.getLogger(OrmProviderFactory.class);
    private static SqlSessionFactory SQL_SESSION_FACTORY=null;

    private OrmProviderFactory(){}

    public void IntiOrm() {
        try {
            TransactionFactory transactionFactory = new JdbcTransactionFactory();
            Environment environment = new Environment("development", transactionFactory, getDataSource());
            Configuration configuration = new Configuration(environment);
            /**映射文件,注意mapper和xml配置文件的路径*/
            configuration.addMappers(config.MODULE_CONFIG);
            SqlSessionFactoryBuilder sessionFactoryBuilder=new SqlSessionFactoryBuilder();
            SQL_SESSION_FACTORY=sessionFactoryBuilder.build(configuration);
        } catch (Exception e) {
            LOGGER.error("初始化mybatis错误，请检查." +
                    "... ...",e);
        }
    }

    private static DataSource getDataSource() throws Exception {
        InputStream fileInputStream= new FileInputStream(config.DATASOURECE_CONFIG);
        Properties properties  = new Properties();
        properties.load(fileInputStream);
        String poolName=properties.getProperty("name");
        if (poolName.equalsIgnoreCase("bonecp")){ //bonecp
            DataSource dataSource=new BoneCPDataSource(new BoneCPConfig(properties));
            fileInputStream.close();
            properties.clear();
           return  dataSource;
        }else if (poolName.equalsIgnoreCase("druid")){  //druid
            DruidDataSource dataSource= new DruidDataSource();
            dataSource.setUsername(properties.getProperty("username"));
            dataSource.setName(poolName);
            dataSource.setPassword(properties.getProperty("password"));
            dataSource.setUrl(properties.getProperty("jdbcurl"));
            dataSource.setDriverClassName(properties.getProperty("driverClass"));
            dataSource.setInitialSize(Integer.parseInt(properties.getProperty("initialSize")));
            dataSource.setMinIdle(Integer.parseInt(properties.getProperty("minIdle")));
            dataSource.setMaxActive(Integer.parseInt(properties.getProperty("maxActive")));
            dataSource.setMaxWait(Long.parseLong(properties.getProperty("maxWait")));

            dataSource.setTimeBetweenEvictionRunsMillis(Long.parseLong(properties.getProperty("timeBetweenEvictionRunsMillis")));
            dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(properties.getProperty("minEvictableIdleTimeMillis")));
            dataSource.setTestWhileIdle(Boolean.parseBoolean(properties.getProperty("testWhileIdle")));
            dataSource.setTestOnReturn(Boolean.parseBoolean(properties.getProperty("testOnReturn")));
            dataSource.setTestOnBorrow(Boolean.parseBoolean(properties.getProperty("testOnBorrow")));

            dataSource.setValidationQuery(properties.getProperty("validationQuery"));
            /**如果是mysql数据库,那么不需要配置下面两个参数*/
            dataSource.setPoolPreparedStatements(Boolean.parseBoolean(properties.getProperty("poolPreparedStatements")));
            dataSource.setMaxPoolPreparedStatementPerConnectionSize(Integer.parseInt(properties.getProperty("maxPoolPreparedStatementPerConnectionSize")));
            dataSource.setUseUnfairLock(Boolean.parseBoolean(properties.getProperty("useUnfairLock")));
            fileInputStream.close();
            properties.clear();
            return  dataSource;
        }else {
            return null;
        }
    }
    /**
     * 获取 SIMPLE sqlSession
     * @return     sqlSession
     */
    public  SqlSession getSimpleSqlSession(){
        return  getSqlSession(ExecutorType.SIMPLE);
    }

    /**
     * 获取  批量执行更新语句 sqlSession
     * @return  sqlSession
     */
    public  SqlSession getBeatchSqlSession(){
      return getSqlSession(ExecutorType.BATCH);
    }

    /**
     *获取  sqlSession
     * @param executorType  SIMPLE, REUSE, BATCH   sqlSession  自动提交事务 autoCommit true
     * @return  sqlSession
     */
    public  SqlSession getSqlSession(ExecutorType executorType){
        return  SQL_SESSION_FACTORY.openSession(executorType,true);
    }

    /**
     * 应用单例
     * @return      OrmProviderFactory
     */
    public static  OrmProviderFactory getOrmProviderFactory(){
        return  singtlon.ORM_PROVIDER_FACTORY;
    }


    private static final class singtlon{
        private static final OrmProviderFactory ORM_PROVIDER_FACTORY=new OrmProviderFactory();
    }
}
